#include<unordered_map>
#include <vector>
#include <queue>

using namespace std;

struct Task{
    
    int userId;
    int taskId;
    int priority;
    bool operator < (const Task& p) const{
        if(priority==p.priority){
            return taskId < p.taskId;
        }
        return priority<p.priority;
    }
};
class TaskManager {

private:
    static const int INF=0x3f3f3f3f;
    unordered_map<int,int> has;
    unordered_map<int,int> userHas;
    priority_queue<Task> q;
public:
    TaskManager(vector<vector<int>>& tasks){
        
        for(int i=0;i<static_cast<int>(tasks.size());++i){
            add(tasks[i][0],tasks[i][1],tasks[i][2]);
        }
    }
    
    void add(int userId, int taskId, int priority) {

        q.push({userId,taskId,priority});
        has[taskId]=priority;
        userHas[taskId]=userId;
    }
    
    void edit(int taskId, int newPriority) {
        
        if(newPriority==has[taskId]){
            return;
        }
        has[taskId]=newPriority;
        q.push({userHas[taskId],taskId,newPriority});
    }
    
    void rmv(int taskId) {
        
        has.erase(taskId);
        userHas.erase(taskId);
    }
    
    int execTop() {
        
        while(q.size()){
            auto u=q.top();
            q.pop();
            if(has.count(u.taskId) && userHas.count(u.taskId) 
                && u.priority==has[u.taskId] && u.userId==userHas[u.taskId]){
                    has.erase(u.taskId);
                    userHas.erase(u.taskId);
                    return u.userId;
            }
        }
        return -1;
    }
};

/**
 * Your TaskManager object will be instantiated and called as such:
 * TaskManager* obj = new TaskManager(tasks);
 * obj->add(userId,taskId,priority);
 * obj->edit(taskId,newPriority);
 * obj->rmv(taskId);
 * int param_4 = obj->execTop();
 */
